﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="JobsAdminControllerTests.cs" company="DST Nexdox">
//   Copyright (c) DST Nexdox. All rights reserved.
// </copyright>
// <summary>
//   Defines the JobsAdminControllerTests type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace WebTests.Controllers
{
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Web.Mvc;
  using System.Web.Script.Serialization;
  using DocProcessingWorkflow.Controllers;
  using DocProcessingWorkflow.Models.JobsAdmin;
  using DocProcessingWorkflow.Models.MailSortSetting;
  using DocProcessingWorkflow.Models.MediaStock;
  using Entities;
  using Exceptions;
  using FluentAssertions;
  using Logging;
  using Moq;
  using NUnit.Framework;
  using ServiceInterfaces;

  [Category("Unit")]
  [TestFixture]
  public class JobsAdminControllerTests : ControllerTestsBase
  {
    private Mock<ILogger> loggerMock;

    private Mock<IAppEnvironmentService> appEnvironmentServiceMock;

    private Mock<IUserService> userServiceMock;

    private Mock<IManCoService> manCoServiceMock;

    private Mock<IManCoDocService> manCoDocServiceMock;

    private Mock<IMediaDefinitionService> mediaDefinitionServiceMock;

    private Mock<IMediaDefinitionAuditService> mediaDefinitionAuditServiceMock;

    private Mock<IMediaStockService> mediaStockServiceMock;

    private Mock<IStockService> stockServiceMock;

    private Mock<IMailSortSettingService> mailSortSettingServiceMock;

    private Mock<IIndexDefinitionService> indexDefinitionServiceMock;

    private JobsAdminController jobsAdminController;

    private ApplicationUser currentUser;

    [SetUp]
    public void Setup()
    {
      this.loggerMock = new Mock<ILogger>();
      this.appEnvironmentServiceMock = new Mock<IAppEnvironmentService>();
      this.userServiceMock = new Mock<IUserService>();
      this.manCoServiceMock = new Mock<IManCoService>();
      this.manCoDocServiceMock = new Mock<IManCoDocService>();
      this.mediaDefinitionServiceMock = new Mock<IMediaDefinitionService>();
      this.mediaDefinitionAuditServiceMock = new Mock<IMediaDefinitionAuditService>();
      this.mediaStockServiceMock = new Mock<IMediaStockService>();
      this.stockServiceMock = new Mock<IStockService>();
      this.mailSortSettingServiceMock = new Mock<IMailSortSettingService>();
      this.indexDefinitionServiceMock = new Mock<IIndexDefinitionService>();

      this.jobsAdminController = new JobsAdminController(
        this.loggerMock.Object,
        this.appEnvironmentServiceMock.Object,
        this.userServiceMock.Object,
        this.manCoServiceMock.Object,
        this.manCoDocServiceMock.Object,
        this.mediaDefinitionServiceMock.Object,
        this.mediaDefinitionAuditServiceMock.Object,
        this.mediaStockServiceMock.Object,
        this.stockServiceMock.Object,
        this.mailSortSettingServiceMock.Object,
        this.indexDefinitionServiceMock.Object);

      this.currentUser = new ApplicationUser("Username") { PreferredEnvironment = "Test" };
    }

    [Test]
    public void GivenAJobsAdminController_WhenTheIndexPageIsAccessed_ThenTheViewIsReturned()
    {
      var manCos = new List<ManagementCompany>
                     {
                       new ManagementCompany { ManCoCode = "Test 1" },
                       new ManagementCompany { ManCoCode = "Test 2" }
                     };

      var mailSortSettings = new List<MailsortSetting>
                                                 {
                                                   new MailsortSetting
                                                     {
                                                       MailsortSettingID = 2,
                                                       nexdoxMailsortService =
                                                         "Test 1"
                                                     },
                                                   new MailsortSetting
                                                     {
                                                       MailsortSettingID = 3,
                                                       nexdoxMailsortService =
                                                         "Test 2"
                                                     }
                                                 };

      this.userServiceMock.Setup(x => x.GetApplicationUser()).Returns(this.currentUser);
      this.manCoServiceMock.Setup(x => x.GetManCos(It.IsAny<String>())).Returns(manCos);
      this.mailSortSettingServiceMock.Setup(x => x.GetMailsortSettings()).Returns(mailSortSettings);

      ViewResult result = this.jobsAdminController.Index();

      this.userServiceMock.Verify(x => x.GetApplicationUser(), Times.Once);
      this.manCoServiceMock.Verify(x => x.GetManCos(It.IsAny<String>()), Times.Once);

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<JobsAdminViewModel>();
      var model = (JobsAdminViewModel)modelObject;

      model.ManCos.Should().HaveCount(2);
      model.ManCos[0].Code.Should().Be("Test 1");
      model.ManCos[1].Code.Should().Be("Test 2");

      model.MailSortSettings.Should().HaveCount(2);
      model.MailSortSettings[0].MailsortSettingID.Should().Be(2);
      model.MailSortSettings[1].MailsortSettingID.Should().Be(3);
    }

    [Test]
    public void GivenAJobsAdminController_WhenTheGetMediaDefinitionsAjaxPageIsRequested_TheViewModelIsConstructed()
    {
      var manCoDoc = new ManCoDoc { ManCoDocID = 1 };

      var mediaDefinitions = new List<MediaDefinitionEntity>
                               {
                                 new MediaDefinitionEntity
                                   {
                                     MediaDefID = 1,
                                     ManCoDocID = 1,
                                     QueueName = "QueueName1",
                                     QueueNameSymbollic =
                                       "QueueNameSymbollic1",
                                     MailSortSettingId = 99,
                                     Print = false,
                                     PDF_Only = false
                                   },
                                 new MediaDefinitionEntity
                                   {
                                     MediaDefID = 2,
                                     ManCoDocID = 1,
                                     QueueName = "QueueName2",
                                     QueueNameSymbollic =
                                       "QueueNameSymbollic2",
                                     MailSortSettingId = 0,
                                     Print = true,
                                     PDF_Only = false
                                   },
                                 new MediaDefinitionEntity
                                   {
                                     MediaDefID = 3,
                                     ManCoDocID = 1,
                                     QueueName = "QueueName3",
                                     QueueNameSymbollic =
                                       "QueueNameSymbollic3",
                                     MailSortSettingId = 0,
                                     Print = false,
                                     PDF_Only = true
                                   }
                               };

      var mediaDefinitionsResult = new PagedResult<MediaDefinitionEntity>
                                     {
                                       CurrentPage = 1,
                                       TotalItems = 5,
                                       ItemsPerPage = 3,
                                       StartRow = 1,
                                       EndRow = 3,
                                       Results = mediaDefinitions
                                     };

      var emptyMediaStockList = new List<MediaStockEntity>();

      var severalMediaStockItems = new List<MediaStockEntity>
                                     {
                                       new MediaStockEntity
                                         {
                                           MediaStockId = 3,
                                           MediaDefId = 1,
                                           StockTypeId = 1,
                                           StockType = "LaserStock",
                                           Code = "STATA",
                                           Description = "Description1",
                                           StationNumber = 1,
                                           Weight = 5,
                                           SizeX = 10,
                                           SizeY = 15,
                                           Facing = "0",
                                           Colour = "White"
                                         },
                                       new MediaStockEntity
                                         {
                                           MediaStockId = 3,
                                           MediaDefId = 2,
                                           StockTypeId = 1,
                                           StockType = "LaserStock",
                                           Code = "STATC",
                                           Description = "Description2",
                                           StationNumber = 3,
                                           Weight = 0,
                                           SizeX = 0,
                                           SizeY = 0,
                                           Facing = "0",
                                           Colour = "Pink TINT"
                                         },
                                       new MediaStockEntity
                                         {
                                           MediaStockId = 3,
                                           MediaDefId = 3,
                                           StockTypeId = 2,
                                           StockType = "Insert",
                                           Code = "Code3",
                                           Description = "Description3",
                                           StationNumber = 1,
                                           Weight = 0,
                                           SizeX = 0,
                                           SizeY = 0,
                                           Facing = "F",
                                           Colour = "White"
                                         },
                                       new MediaStockEntity
                                         {
                                           MediaStockId = 3,
                                           MediaDefId = 4,
                                           StockTypeId = 3,
                                           StockType = "Outer",
                                           Code = "Code4",
                                           Description = "Description4",
                                           StationNumber = 1,
                                           Weight = 0,
                                           SizeX = 0,
                                           SizeY = 0,
                                           Facing = "0",
                                           Colour = "White"
                                         }
                                     };

      this.manCoDocServiceMock.Setup(
        x => x.GetManCoDoc(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<String>(), It.IsAny<String>()))
        .Returns(manCoDoc);

      this.mediaDefinitionServiceMock.Setup(
        x => x.GetByManCoDoc(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>())).Returns(mediaDefinitionsResult);

      this.mediaStockServiceMock.SetupSequence(x => x.GetByMediaDefinition(It.IsAny<Int32>()))
        .Returns(emptyMediaStockList)
        .Returns(emptyMediaStockList)
        .Returns(severalMediaStockItems)
        .Throws(new Exception("Test does not support a fourth item"));

      PartialViewResult result = this.jobsAdminController.GetMediaDefinitionsAjax(
        "environment",
        "manCoCode",
        "documentTypeCode",
        "documentTypeDescription");

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<JobsAdminMediaDefinitionsViewModel>();
      var model = (JobsAdminMediaDefinitionsViewModel)modelObject;

      model.PagingInfo.TotalItems.Should().Be(5);
      model.PagingInfo.ItemsPerPage.Should().Be(3);
      model.MediaDefinitions.Should().HaveCount(3);

      model.MediaDefinitions[0].QueueName.Should().Be("QueueName1");
      model.MediaDefinitions[0].MailSortSettingId.Should().Be(99);
      model.MediaDefinitions[0].MailSorted.Should().Be(true);
      model.MediaDefinitions[0].Print.Should().Be(false);
      model.MediaDefinitions[0].PdfOnly.Should().Be(false);
      model.MediaDefinitions[0].Inserts.Should().HaveCount(0);
      model.MediaDefinitions[0].Trays.Should().HaveCount(0);
      model.MediaDefinitions[0].Envelopes.Should().HaveCount(0);

      model.MediaDefinitions[1].QueueName.Should().Be("QueueName2");
      model.MediaDefinitions[1].MailSortSettingId.Should().Be(0);
      model.MediaDefinitions[1].MailSorted.Should().Be(false);
      model.MediaDefinitions[1].Print.Should().Be(true);
      model.MediaDefinitions[1].PdfOnly.Should().Be(false);
      model.MediaDefinitions[1].Inserts.Should().HaveCount(0);
      model.MediaDefinitions[1].Trays.Should().HaveCount(0);
      model.MediaDefinitions[1].Envelopes.Should().HaveCount(0);

      model.MediaDefinitions[2].QueueName.Should().Be("QueueName3");
      model.MediaDefinitions[2].MailSortSettingId.Should().Be(0);
      model.MediaDefinitions[2].MailSorted.Should().Be(false);
      model.MediaDefinitions[2].Print.Should().Be(false);
      model.MediaDefinitions[2].PdfOnly.Should().Be(true);
      model.MediaDefinitions[2].Inserts.Should().HaveCount(1);
      model.MediaDefinitions[2].Trays.Should().HaveCount(2);
      model.MediaDefinitions[2].Envelopes.Should().HaveCount(1);

      model.MediaDefinitions[2].Inserts[0].Code.Should().Be("Code3");
      model.MediaDefinitions[2].Inserts[0].Facing.Should().Be("F");

      model.MediaDefinitions[2].Trays[0].Code.Should().Be("STATA");
      model.MediaDefinitions[2].Trays[0].Weight.Should().Be(5);
      model.MediaDefinitions[2].Trays[0].SizeX.Should().Be(10);
      model.MediaDefinitions[2].Trays[0].SizeY.Should().Be(15);

      model.MediaDefinitions[2].Trays[1].Code.Should().Be("STATC");
      model.MediaDefinitions[2].Trays[1].StationNumber.Should().Be(3);
      model.MediaDefinitions[2].Trays[1].Facing.Should().Be("0");
      model.MediaDefinitions[2].Trays[1].Colour.Should().Be("Pink TINT");

      model.MediaDefinitions[2].Envelopes[0].Code.Should().Be("Code4");
    }

    [Test]
    public void GivenAJobsAdminController_WhenTheGetMediaDefinitionAuditsAjaxPageIsRequested_TheViewModelIsConstructed()
    {
      var audits = new List<MediaDefinitionAuditEntity>
                     {
                       new MediaDefinitionAuditEntity
                         {
                           MediaDefinitionAuditId = 1,
                           AuditType = MediaDefinitionAudit.MediaDefinitionAuditType.PrintFlagUpdated,
                           AuditDate = new DateTime(2015, 1, 1),
                           Details = "audit details",
                           UserId = "test",
                           Username = "test user"
                         },
                       new MediaDefinitionAuditEntity
                         {
                           MediaDefinitionAuditId = 2,
                           AuditType = MediaDefinitionAudit.MediaDefinitionAuditType.MediaStockStationNumbersUpdated,
                           AuditDate = new DateTime(2015, 1, 2),
                           Details = "audit details 2",
                           UserId = "test",
                           Username = "test user"
                         }
                     };

      this.mediaDefinitionAuditServiceMock.Setup(x => x.GetAudits(It.IsAny<Int32>())).Returns(audits);

      PartialViewResult result = this.jobsAdminController.GetMediaDefinitionAuditsAjax(1);

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<MediaDefinitionAuditsViewModel>();
      var model = (MediaDefinitionAuditsViewModel)modelObject;

      model.Audits.Should().HaveCount(2);
      model.Audits[0].AuditDate.Should().Be(new DateTime(2015, 1, 1));
      model.Audits[0].Details.Should().Be("audit details");
      model.Audits[0].UserName.Should().Be("test user");
      model.Audits[1].AuditDate.Should().Be(new DateTime(2015, 1, 2));
      model.Audits[1].Details.Should().Be("audit details 2");
      model.Audits[1].UserName.Should().Be("test user");
    }

    [Test]
    public void GivenAJobsAdminController_WhenIUpdateAMediaDefinitionPrintFlag_TheDatabaseIsUpdated()
    {
      this.jobsAdminController.UpdatePrintFlag(1, true);

      this.mediaDefinitionServiceMock.Verify(s => s.UpdatePrintFlag(1, true), Times.Once);
    }

    [Test]
    public void GivenAJobsAdminController_WhenIUpdateAMediaDefinitionPrintFlag_ASuccessObjectIsReturned()
    {
      JsonResult result = this.jobsAdminController.UpdatePrintFlag(1, true);

      result.Data.ToString().Should().Be("{ Success = True }");
    }

    [Test]
    public void GivenAJobsAdminController_WhenIUpdateAMediaDefinitionsMailSortSetting_TheDatabaseIsUpdated()
    {
      this.jobsAdminController.UpdateMailSortSetting(1, 9);

      this.indexDefinitionServiceMock.Verify(s => s.UpdateMailSortSetting(1, 9), Times.Once);
    }

    [Test]
    public void GivenAJobsAdminController_WhenIUpdateAMediaDefinitionsMailSortSetting_ASuccessObjectIsReturned()
    {
      JsonResult result = this.jobsAdminController.UpdateMailSortSetting(1, 9);

      result.Data.ToString().Should().Be("{ Success = True }");
    }

    [Test]
    public void GivenValidData_WhenTheAssignmentStockAjaxPageIsRequested_TheViewModelIsConstructed()
    {
      var singleMediaStockItem = new List<MediaStockEntity>
                                   {
                                     new MediaStockEntity
                                       {
                                         StockId = 1,
                                         MediaStockId = 3,
                                         MediaDefId = 1,
                                         StockTypeId = 1,
                                         StockType = "LaserStock",
                                         Code = "STATA",
                                         Description = "Description1",
                                         StationNumber = 1,
                                         Weight = 5,
                                         SizeX = 10,
                                         SizeY = 15,
                                         Facing = "0",
                                         Colour = "White"
                                       }
                                   };

      var stockEntityItems = new List<StockEntity>
                               {
                                 new StockEntity
                                   {
                                     StockId = 2,
                                     Code = "Code2",
                                     Description = "Description2",
                                     Colour = "Red",
                                     Weight = 6,
                                     SizeX = 7,
                                     SizeY = 8,
                                     Facing = "0"
                                   }
                               };

      this.mediaStockServiceMock.Setup(mss => mss.GetByMediaDefinition(It.IsAny<Int32>())).Returns(singleMediaStockItem);

      this.stockServiceMock.Setup(ssm => ssm.GetStockByType(It.IsAny<String>(), It.IsAny<String>()))
        .Returns(stockEntityItems);

      PartialViewResult result = this.jobsAdminController.AssignmentStockAjax(10, "LaserStock", "filter");

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<StockAssignmentViewModel>();
      var model = (StockAssignmentViewModel)modelObject;

      model.MediaDefinitionId.Should().Be(10);

      model.ExistingStock.Should().HaveCount(1);
      model.ExistingStock[0].MediaStockId.Should().Be(3);
      model.ExistingStock[0].Code.Should().Be("STATA");
      model.ExistingStock[0].Description.Should().Be("Description1");
      model.ExistingStock[0].Weight.Should().Be(5);
      model.ExistingStock[0].SizeX.Should().Be(10);
      model.ExistingStock[0].SizeY.Should().Be(15);
      model.ExistingStock[0].Facing.Should().Be("0");
      model.ExistingStock[0].Colour.Should().Be("White");

      model.AvailableStock.Should().HaveCount(1);
      model.AvailableStock[0].StockId.Should().Be(2);
      model.AvailableStock[0].Code.Should().Be("Code2");
      model.AvailableStock[0].Description.Should().Be("Description2");
      model.AvailableStock[0].Colour.Should().Be("Red");
      model.AvailableStock[0].Weight.Should().Be(6);
      model.AvailableStock[0].SizeX.Should().Be(7);
      model.AvailableStock[0].SizeY.Should().Be(8);
      model.AvailableStock[0].Facing.Should().Be("0");
    }

    [Test]
    public void
      GivenValidData_WhenTheAssignmentStockAjaxPageIsRequested_AndItemsHaveArleadyBeenSelected_TheSelectedItemsAreExcludedFromTheAvailableList()
    {
      var singleMediaStockItem = new List<MediaStockEntity>
                                   {
                                     new MediaStockEntity
                                       {
                                         StockId = 1,
                                         MediaStockId = 3,
                                         MediaDefId = 1,
                                         StockTypeId = 1,
                                         StockType = "LaserStock",
                                         Code = "STATA",
                                         Description = "Description1",
                                         StationNumber = 1,
                                         Weight = 5,
                                         SizeX = 10,
                                         SizeY = 15,
                                         Facing = "0",
                                         Colour = "White"
                                       }
                                   };

      var stockEntityItems = new List<StockEntity>
                               {
                                 new StockEntity
                                   {
                                     StockId = 1,
                                     Code = "STATA",
                                     Description = "Description1",
                                     Colour = "White"
                                   },
                                 new StockEntity
                                   {
                                     StockId = 2,
                                     Code = "Code2",
                                     Description = "Description2",
                                     Colour = "Red",
                                     Weight = 6,
                                     SizeX = 7,
                                     SizeY = 8,
                                     Facing = "0"
                                   }
                               };

      this.mediaStockServiceMock.Setup(mss => mss.GetByMediaDefinition(It.IsAny<Int32>())).Returns(singleMediaStockItem);

      this.stockServiceMock.Setup(ssm => ssm.GetStockByType(It.IsAny<String>(), It.IsAny<String>()))
        .Returns(stockEntityItems);

      PartialViewResult result = this.jobsAdminController.AssignmentStockAjax(10, "LaserStock", "filter");

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<StockAssignmentViewModel>();
      var model = (StockAssignmentViewModel)modelObject;

      model.ExistingStock.Should().HaveCount(1);
      model.ExistingStock[0].MediaStockId.Should().Be(3);
      model.ExistingStock[0].Code.Should().Be("STATA");

      model.AvailableStock.Should().HaveCount(1);
      model.AvailableStock[0].StockId.Should().Be(2);
      model.AvailableStock[0].Code.Should().Be("Code2");
    }

    [Test]
    public void GivenValidData_WhenTheAssignmentStockAjaxPageIsRequested_ForTrays_TheViewModelIsConstructed()
    {
      this.mediaStockServiceMock.Setup(mss => mss.GetByMediaDefinition(It.IsAny<Int32>()))
        .Returns(new List<MediaStockEntity>());

      this.stockServiceMock.Setup(ssm => ssm.GetStockByType(It.IsAny<String>(), It.IsAny<String>()))
        .Returns(new List<StockEntity>());

      PartialViewResult result = this.jobsAdminController.AssignmentStockAjax(10, "LaserStock", "filter");

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<StockAssignmentViewModel>();
      var model = (StockAssignmentViewModel)modelObject;

      model.StockType.Should().Be("LaserStock");
      model.DisplayStockType.Should().Be("Trays");
      model.DisplayStockTypeSingular.Should().Be("Tray");
      model.AllowEditingStationNumbers = false;
    }

    [Test]
    public void GivenValidData_WhenTheAssignmentStockAjaxPageIsRequested_ForInserts_TheViewModelIsConstructed()
    {
      this.mediaStockServiceMock.Setup(mss => mss.GetByMediaDefinition(It.IsAny<Int32>()))
        .Returns(new List<MediaStockEntity>());

      this.stockServiceMock.Setup(ssm => ssm.GetStockByType(It.IsAny<String>(), It.IsAny<String>()))
        .Returns(new List<StockEntity>());

      PartialViewResult result = this.jobsAdminController.AssignmentStockAjax(10, "Insert", "filter");

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<StockAssignmentViewModel>();
      var model = (StockAssignmentViewModel)modelObject;

      model.StockType.Should().Be("Insert");
      model.DisplayStockType.Should().Be("Inserts");
      model.DisplayStockTypeSingular.Should().Be("Insert");
      model.AllowEditingStationNumbers = true;
    }

    [Test]
    public void GivenValidData_WhenTheAssignmentStockAjaxPageIsRequested_ForEnvelopes_TheViewModelIsConstructed()
    {
      this.mediaStockServiceMock.Setup(mss => mss.GetByMediaDefinition(It.IsAny<Int32>()))
        .Returns(new List<MediaStockEntity>());

      this.stockServiceMock.Setup(ssm => ssm.GetStockByType(It.IsAny<String>(), It.IsAny<String>()))
        .Returns(new List<StockEntity>());

      PartialViewResult result = this.jobsAdminController.AssignmentStockAjax(10, "Outer", "filter");

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<StockAssignmentViewModel>();
      var model = (StockAssignmentViewModel)modelObject;

      model.StockType.Should().Be("Outer");
      model.DisplayStockType.Should().Be("Envelope Stock");
      model.DisplayStockTypeSingular.Should().Be("Envelope");
      model.AllowEditingStationNumbers = false;
    }

    [Test]
    public void GivenValidData_WhenTheAssignmentStockAjaxPageIsRequested_WithAnEmptyFilter_NoAvailableItemsAreReturned()
    {
      var singleMediaStockItem = new List<MediaStockEntity>
                                   {
                                     new MediaStockEntity
                                       {
                                         StockId = 1,
                                         MediaStockId = 3,
                                         MediaDefId = 1,
                                         StockTypeId = 1,
                                         StockType = "LaserStock",
                                         Code = "STATA",
                                         Description = "Description1",
                                         StationNumber = 1,
                                         Weight = 5,
                                         SizeX = 10,
                                         SizeY = 15,
                                         Facing = "0",
                                         Colour = "White"
                                       }
                                   };

      var stockEntityItems = new List<StockEntity>
                               {
                                 new StockEntity
                                   {
                                     StockId = 2,
                                     Code = "Code2",
                                     Description = "Description2",
                                     Colour = "Red",
                                     Weight = 6,
                                     SizeX = 7,
                                     SizeY = 8,
                                     Facing = "0"
                                   }
                               };

      this.mediaStockServiceMock.Setup(mss => mss.GetByMediaDefinition(It.IsAny<Int32>())).Returns(singleMediaStockItem);

      this.stockServiceMock.Setup(ssm => ssm.GetStockByType(It.IsAny<String>(), It.IsAny<String>()))
        .Returns(stockEntityItems);

      PartialViewResult result = this.jobsAdminController.AssignmentStockAjax(10, "LaserStock", String.Empty);

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<StockAssignmentViewModel>();
      var model = (StockAssignmentViewModel)modelObject;

      model.ExistingStock.Should().HaveCount(1);
      model.AvailableStock.Should().HaveCount(0);
    }

    [Test]
    public void GivenValidData_WhenTheAssignmentStockAjaxPageIsRequested_ForAnUnsupportedType_AnExceptionIsRaised()
    {
      this.mediaStockServiceMock.Setup(mss => mss.GetByMediaDefinition(It.IsAny<Int32>()))
        .Returns(new List<MediaStockEntity>());

      this.stockServiceMock.Setup(ssm => ssm.GetStockByType(It.IsAny<String>(), It.IsAny<String>()))
        .Returns(new List<StockEntity>());

      try
      {
        this.jobsAdminController.AssignmentStockAjax(10, "UnsupportedType", "filter");
      }
      catch (Exception ex)
      {
        ex.Message.Should().Be("StockType 'UnsupportedType' not supported");
      }
    }

    [Test]
    public void GivenAMediaDefinitionIdAndStockType_WhenStationNumbersAreChecked_AndNoAssignmentsAreSubmitted_AFailureObjectIsReturned()
    {
      var emptyStationNumberAssignments = new List<StationNumberAssignmentViewModel>();

      JsonResult result = this.jobsAdminController.UpdateStationNumbersIsAvailable(1, "LaserStock", emptyStationNumberAssignments);

      result.Data.ToString().Should().Be("{ Result = False }");
    }

    [Test]
    public void GivenValidData_WhenStationNumbersAreChecked_AndADuplicateIsFound_AFailureObjectIsReturned()
    {
      var existingMediaStockItems = new List<MediaStockEntity>
                                      {
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 1,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "Insert",
                                            Code = "Code1",
                                            StationNumber = 1
                                          },
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 2,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "Insert",
                                            Code = "Code2",
                                            StationNumber = 2
                                          },
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 3,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "Insert",
                                            Code = "Code3",
                                            StationNumber = 3
                                          }
                                      };

      var stationNumberAssignments = new List<StationNumberAssignmentViewModel>
                                       {
                                         new StationNumberAssignmentViewModel
                                           {
                                             MediaStockId
                                               =
                                               1,
                                             StationNumber
                                               =
                                               2
                                           },
                                         new StationNumberAssignmentViewModel
                                           {
                                             MediaStockId
                                               =
                                               3,
                                             StationNumber
                                               =
                                               1
                                           }
                                       };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItems);

      JsonResult result = this.jobsAdminController.UpdateStationNumbersIsAvailable(1, "Insert", stationNumberAssignments);

      result.Data.ToString().Should().Be("{ Result = False }");
    }

    [Test]
    public void GivenValidData_WhenStationNumbersAreChecked_ForTrays_AFailureObjectIsReturned()
    {
      var assignment = new List<StationNumberAssignmentViewModel> { new StationNumberAssignmentViewModel { MediaStockId = 1, StationNumber = 1 } };

      JsonResult result = this.jobsAdminController.UpdateStationNumbersIsAvailable(1, "LaserStock", assignment);

      result.Data.ToString().Should().Be("{ Result = False }");
    }

    [Test]
    public void GivenValidData_WhenStationNumbersAreChecked_ForEnvelopes_AFailureObjectIsReturned()
    {
      var assignment = new List<StationNumberAssignmentViewModel> { new StationNumberAssignmentViewModel { MediaStockId = 1, StationNumber = 1 } };

      JsonResult result = this.jobsAdminController.UpdateStationNumbersIsAvailable(1, "Outer", assignment);

      result.Data.ToString().Should().Be("{ Result = False }");
    }

    [Test]
    public void GivenValidData_WhenStationNumbersAreChecked_AndTheNumberIsValidForInserts_ASuccessObjectIsReturned()
    {
      var existingMediaStockItem = new List<MediaStockEntity>
                                     {
                                       new MediaStockEntity
                                         {
                                           MediaStockId = 1,
                                           MediaDefId = 1,
                                           StockTypeId = 1,
                                           StockType = "Insert",
                                           Code = "Code1",
                                           StationNumber = 1
                                         }
                                     };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItem);

      var validStationNumbers = new List<Int32> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

      foreach (Int32 validStationNumber in validStationNumbers)
      {
        var stationNumberAssignment = new List<StationNumberAssignmentViewModel>
                                        {
                                          new StationNumberAssignmentViewModel
                                            {
                                              MediaStockId
                                                =
                                                1,
                                              StationNumber
                                                =
                                                validStationNumber
                                            }
                                        };

        JsonResult result = this.jobsAdminController.UpdateStationNumbersIsAvailable(
          1,
          "Insert",
          stationNumberAssignment);

        result.Data.ToString().Should().Be("{ Result = True }");
      }
    }

    [Test]
    public void GivenValidData_WhenStationNumbersAreChecked_AndTheNumberIsInvalidForInserts_AFailureObjectIsReturned()
    {
            var existingMediaStockItem = new List<MediaStockEntity>
                                     {
                                       new MediaStockEntity
                                         {
                                           MediaStockId = 1,
                                           MediaDefId = 1,
                                           StockTypeId = 1,
                                           StockType = "Insert",
                                           Code = "Code1",
                                           StationNumber = 1
                                         }
                                     };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItem);

      var invalidStationNumbers = new List<Int32> { -1, 0, 10, 100 };

      foreach (Int32 validStationNumber in invalidStationNumbers)
      {
        var stationNumberAssignment = new List<StationNumberAssignmentViewModel>
                                        {
                                          new StationNumberAssignmentViewModel
                                            {
                                              MediaStockId
                                                =
                                                1,
                                              StationNumber
                                                =
                                                validStationNumber
                                            }
                                        };

        JsonResult result = this.jobsAdminController.UpdateStationNumbersIsAvailable(1, "Insert", stationNumberAssignment);

        result.Data.ToString().Should().Be("{ Result = False }");
      }
    }

    [Test]
    public void GivenAMediaDefinitionIdAndStockType_WhenStationNumbersAreUpdated_AndNoAssignmentsAreSubmitted_AnExceptionIsRaised()
    {
      var emptyStationNumberAssignments = new List<StationNumberAssignmentViewModel>();

      Action act = () => this.jobsAdminController.UpdateStationNumbers(1, "LaserStock", emptyStationNumberAssignments);

      act.ShouldThrow<ArgumentException>();
    }

    [Test]
    public void GivenValidData_WhenStationNumbersAreUpdated_TheDatabaseIsUpdated()
    {
      var existingMediaStockItems = new List<MediaStockEntity>
                                      {
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 1,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "Insert",
                                            Code = "Code1",
                                            StationNumber = 1
                                          },
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 2,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "Insert",
                                            Code = "Code2",
                                            StationNumber = 2
                                          }
                                      };

      var stationNumberAssignments = new List<StationNumberAssignmentViewModel>
                                       {
                                         new StationNumberAssignmentViewModel
                                           {
                                             MediaStockId
                                               =
                                               1,
                                             StationNumber
                                               =
                                               2
                                           },
                                         new StationNumberAssignmentViewModel
                                           {
                                             MediaStockId
                                               =
                                               2,
                                             StationNumber
                                               =
                                               1
                                           }
                                       };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItems);

      List<StationNumberAssignment> assignmentsSubmitted = null;

      this.mediaStockServiceMock.Setup(s => s.UpdateStationNumbers(It.IsAny<Int32>(), It.IsAny<List<StationNumberAssignment>>()))
        .Callback<Int32, List<StationNumberAssignment>>((mediaDefId, assignments) => { assignmentsSubmitted = assignments; });

      this.jobsAdminController.UpdateStationNumbers(1, "Insert", stationNumberAssignments);

      this.mediaStockServiceMock.Verify(
        s => s.UpdateStationNumbers(1, It.IsAny<List<StationNumberAssignment>>()),
        Times.Once);

      assignmentsSubmitted.Should().HaveCount(2);
      assignmentsSubmitted[0].MediaStockID.Should().Be(1);
      assignmentsSubmitted[0].StationNumber.Should().Be(2);

      assignmentsSubmitted[1].MediaStockID.Should().Be(2);
      assignmentsSubmitted[1].StationNumber.Should().Be(1);
    }

    [Test]
    public void GivenValidData_WhenStationNumbersAreUpdated_TheViewModelIsConstructed()
    {
      var existingMediaStockItems = new List<MediaStockEntity>
                                      {
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 1,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "Insert",
                                            Code = "Code1",
                                            StationNumber = 1
                                          },
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 2,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "Insert",
                                            Code = "Code2",
                                            StationNumber = 3
                                          },
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 3,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "Insert",
                                            Code = "Code3",
                                            StationNumber = 2
                                          }
                                      };

      var stationNumberAssignments = new List<StationNumberAssignmentViewModel>
                                       {
                                         new StationNumberAssignmentViewModel
                                           {
                                             MediaStockId
                                               =
                                               1,
                                             StationNumber
                                               =
                                               2
                                           },
                                         new StationNumberAssignmentViewModel
                                           {
                                             MediaStockId
                                               =
                                               3,
                                             StationNumber
                                               =
                                               1
                                           }
                                       };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItems);

      PartialViewResult result = this.jobsAdminController.UpdateStationNumbers(
        1,
        "Insert",
        stationNumberAssignments);

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<List<MediaStockViewModel>>();
      var model = (List<MediaStockViewModel>)modelObject;

      model.Count.Should().Be(3);

      MediaStockViewModel code1 = model.Single(ms => ms.MediaStockId == 1);
      MediaStockViewModel code2 = model.Single(ms => ms.MediaStockId == 2);
      MediaStockViewModel code3 = model.Single(ms => ms.MediaStockId == 3);

      code1.StationNumber.Should().Be(2);
      code2.StationNumber.Should().Be(3);
      code3.StationNumber.Should().Be(1);
    }

    [Test]
    public void GivenValidData_WhenStationNumbersAreUpdated_AndADuplicateIsFound_AnExceptionIsRaised()
    {
      var existingMediaStockItems = new List<MediaStockEntity>
                                      {
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 1,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "Insert",
                                            Code = "Code1",
                                            StationNumber = 1
                                          },
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 2,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "Insert",
                                            Code = "Code2",
                                            StationNumber = 2
                                          },
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 3,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "Insert",
                                            Code = "Code3",
                                            StationNumber = 3
                                          }
                                      };

      var stationNumberAssignments = new List<StationNumberAssignmentViewModel>
                                       {
                                         new StationNumberAssignmentViewModel
                                           {
                                             MediaStockId
                                               =
                                               1,
                                             StationNumber
                                               =
                                               2
                                           },
                                         new StationNumberAssignmentViewModel
                                           {
                                             MediaStockId
                                               =
                                               3,
                                             StationNumber
                                               =
                                               1
                                           }
                                       };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItems);

      try
      {
        this.jobsAdminController.UpdateStationNumbers(1, "Insert", stationNumberAssignments);
      }
      catch (Exception ex)
      {
        ex.Message.Should().Be("Station number duplicated");
        return;
      }

      Assert.Fail("Exception should be raised");
    }

    [Test]
    public void GivenValidData_WhenStationNumbersAreUpdated_ForTrays_AnArgumentExceptionIsRaised()
    {
      var assignment = new List<StationNumberAssignmentViewModel> { new StationNumberAssignmentViewModel { MediaStockId = 1, StationNumber = 1 } };

      try
      {
        this.jobsAdminController.UpdateStationNumbers(1, "LaserStock", assignment);
      }
      catch (ArgumentException ex)
      {
        ex.Message.Should().Be("StockType 'LaserStock' cannot have its station numbers updated");
        return;
      }

      Assert.Fail("An ArgumentException should be raised");
    }

    [Test]
    public void GivenValidData_WhenStationNumbersAreUpdated_AndTheNumberIsValidForInserts_NoExceptionIsRaised()
    {
      var existingMediaStockItem = new List<MediaStockEntity>
                                     {
                                       new MediaStockEntity
                                         {
                                           MediaStockId = 1,
                                           MediaDefId = 1,
                                           StockTypeId = 1,
                                           StockType = "Insert",
                                           Code = "Code1",
                                           StationNumber = 1
                                         }
                                     };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItem);

      var validStationNumbers = new List<Int32> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

      foreach (Int32 validStationNumber in validStationNumbers)
      {
        var stationNumberAssignment = new List<StationNumberAssignmentViewModel>
                                        {
                                          new StationNumberAssignmentViewModel { MediaStockId = 1, StationNumber = validStationNumber }
                                        };

        Action act = () => this.jobsAdminController.UpdateStationNumbers(1, "Insert", stationNumberAssignment);

        act.ShouldNotThrow();
      }
    }

    [Test]
    public void GivenValidData_WhenStationNumbersAreUpdated_AndTheNumberIsInvalidForInserts_AnExceptionIsRaised()
    {
      var existingMediaStockItem = new List<MediaStockEntity>
                                     {
                                       new MediaStockEntity
                                         {
                                           MediaStockId = 1,
                                           MediaDefId = 1,
                                           StockTypeId = 1,
                                           StockType = "Insert",
                                           Code = "Code1",
                                           StationNumber = 1
                                         }
                                     };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItem);

      var invalidStationNumbers = new List<Int32> { -1, 0, 10, 100 };

      foreach (Int32 validStationNumber in invalidStationNumbers)
      {
        var stationNumberAssignment = new List<StationNumberAssignmentViewModel>
                                        {
                                          new StationNumberAssignmentViewModel { MediaStockId = 1, StationNumber = validStationNumber }
                                        };

        try
        {
          this.jobsAdminController.UpdateStationNumbers(1, "Insert", stationNumberAssignment);
        }
        catch (Exception ex)
        {
          ex.Message.Should().Be("Station number invalid");
          continue;
        }

        Assert.Fail("An exception should be raised");
      }
    }

    [Test]
    public void GivenValidData_WhenStationNumbersAreUpdated_ForEnvelopes_AnArgumentExceptionIsRaised()
    {
      var assignment = new List<StationNumberAssignmentViewModel> { new StationNumberAssignmentViewModel { MediaStockId = 1, StationNumber = 1 } };

      try
      {
        this.jobsAdminController.UpdateStationNumbers(1, "Outer", assignment);
      }
      catch (ArgumentException ex)
      {
        ex.Message.Should().Be("StockType 'Outer' cannot have its station numbers updated");
        return;
      }

      Assert.Fail("An ArgumentException should be raised");
    }

    [Test]
    public void GivenValidData_WhenIRemoveMediaStock_TheDatabaseIsUpdated()
    {
      var existingMediaStockItems = new List<MediaStockEntity>
                                      {
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 1,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 1
                                          },
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 2,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 2
                                          }
                                      };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItems);

      this.jobsAdminController.RemoveMediaStock(1, "LaserStock", 1, String.Empty);

      this.mediaStockServiceMock.Verify(s => s.RemoveMediaStock(1), Times.Once);
    }

    [Test]
    public void GivenValidData_WhenIRemoveMediaStock_TheViewModelIsConstructed()
    {
      var existingMediaStockItems = new List<MediaStockEntity>
                                      {
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 1,
                                            Code = "Code1",
                                            StockId = 5,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 1,
                                            Description = "Custom Description MyFilter MoreText",
                                            Weight = 7,
                                            SizeX = 8,
                                            SizeY = 9,
                                            Colour = "Blue",
                                            Facing = "F"
                                          },
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 2,
                                            Code = "Code2",
                                            StockId = 10,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 2,
                                            Description = "MyFilter And Other Text"
                                          }
                                      };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItems);

      var availableStockAfterRemoval = new List<StockEntity>
                                         {
                                           new StockEntity
                                             {
                                               StockId = 10,
                                               Code = "Code1",
                                               Description = "MyFilter And Other Text",
                                               Weight = 3,
                                               SizeX = 6,
                                               SizeY = 9,
                                               Colour = "Green",
                                               Facing = "0"
                                             }
                                         };

      this.stockServiceMock
        .Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>()))
        .Returns(availableStockAfterRemoval);

      PartialViewResult result = this.jobsAdminController.RemoveMediaStock(1, "LaserStock", 2, "MyFilter");

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<StockAssignmentViewModel>();
      var model = (StockAssignmentViewModel)modelObject;

      model.MediaDefinitionId.Should().Be(1);
      model.StockType.Should().Be("LaserStock");
      model.DisplayStockType.Should().Be("Trays");
      model.Filter.Should().Be("MyFilter");
      model.ExistingStock.Should().HaveCount(1);
      model.AvailableStock.Should().HaveCount(1);

      model.ExistingStock[0].MediaStockId.Should().Be(1);
      model.ExistingStock[0].Code.Should().Be("Code1");
      model.ExistingStock[0].Description.Should().Be("Custom Description MyFilter MoreText");
      model.ExistingStock[0].StationNumber.Should().Be(1);
      model.ExistingStock[0].Weight.Should().Be(7);
      model.ExistingStock[0].SizeX.Should().Be(8);
      model.ExistingStock[0].SizeY.Should().Be(9);
      model.ExistingStock[0].Colour.Should().Be("Blue");
      model.ExistingStock[0].Facing.Should().Be("F");

      model.AvailableStock[0].StockId.Should().Be(10);
      model.AvailableStock[0].Code.Should().Be("Code1");
      model.AvailableStock[0].Description.Should().Be("MyFilter And Other Text");
      model.AvailableStock[0].Weight.Should().Be(3);
      model.AvailableStock[0].SizeX.Should().Be(6);
      model.AvailableStock[0].SizeY.Should().Be(9);
      model.AvailableStock[0].Colour.Should().Be("Green");
      model.AvailableStock[0].Facing.Should().Be("0");
    }

    [Test]
    public void GivenValidData_WhenIRemoveMediaStock_AndTheItemIsNotAlreadyAssigned_AnExceptionIsRaised()
    {
      var existingMediaStockItem = new List<MediaStockEntity>
                                      {
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 1,
                                            Code = "Code1",
                                            StockId = 5,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 1,
                                            Description = "Custom Description MyFilter MoreText",
                                          }
                                      };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItem);

      try
      {
        this.jobsAdminController.RemoveMediaStock(1, "LaserStock", 2, "MyFilter");
      }
      catch (Exception ex)
      {
        ex.Message.Should().Be("Item not already assigned");
      }
    }

    [Test]
    public void GivenValidData_WhenICheckIfMediaStockCanBeAdded_AndADuplicateIsFound_AFailureObjectIsReturned()
    {
      var existingMediaStockItems = new List<MediaStockEntity>
                                      {
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 1,
                                            StockId = 1,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 1
                                          },
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 2,
                                            StockId = 2,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 2
                                          }
                                      };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItems);

      var stockItems = new List<StockEntity>
                         {
                           new StockEntity { StockId = 10, Code = "STATB" }
                         };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var stockToAdd = new List<AssignStockViewModel>
                         {
                           new AssignStockViewModel { StockId = 10, StationNumber = 2 }
                         };

      this.mediaStockServiceMock
        .Setup(s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
        .Returns(new MediaStockEntity { MediaStockId = 3, StockId = 11, StationNumber = 4 });

      JsonResult result = this.jobsAdminController.AddMediaStockIsAvailable(1, "LaserStock", stockToAdd);

      result.Data.ToString().Should().Be("{ Result = False }");
    }

    [Test]
    public void GivenValidData_WhenICheckIfMediaStockCanBeAdded_WithDuplicatesInTheSubmittedData_AFailureObjectIsReturned()
    {
     var existingMediaStockItem = new List<MediaStockEntity>
                                      {
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 1,
                                            StockId = 1,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 1
                                          }
                                      };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItem);

      var stockItems = new List<StockEntity>
                         {
                           new StockEntity { StockId = 10, Code = "STATB" },
                           new StockEntity { StockId = 15, Code = "STATB" }
                         };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var stockToAdd = new List<AssignStockViewModel>
                         {
                           new AssignStockViewModel { StockId = 10, StationNumber = 2 },
                           new AssignStockViewModel { StockId = 15, StationNumber = 2 }
                         };

      JsonResult result = this.jobsAdminController.AddMediaStockIsAvailable(1, "LaserStock", stockToAdd);

      result.Data.ToString().Should().Be("{ Result = False }");
    }

    [Test]
    public void GivenValidData_WhenICheckIfMediaStockCanBeAdded_AndTheNumberIsValidForTrays_ASuccessObjectIsReturned()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity>
                         {
                           new StockEntity { StockId = 10, Code = "STATA" },
                           new StockEntity { StockId = 11, Code = "STATB" },
                           new StockEntity { StockId = 12, Code = "STATC" },
                           new StockEntity { StockId = 13, Code = "STATD" },
                           new StockEntity { StockId = 14, Code = "STATE" },
                           new StockEntity { StockId = 15, Code = "STATF" }
                         };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      // Item1 = StockId
      // Item2 = Station Number
      var validStationNumbers = new List<Tuple<Int32, Int32>>
                                   {
                                     new Tuple<Int32, Int32>(10, 1),
                                     new Tuple<Int32, Int32>(11, 2),
                                     new Tuple<Int32, Int32>(12, 3),
                                     new Tuple<Int32, Int32>(13, 4),
                                     new Tuple<Int32, Int32>(14, 5),
                                     new Tuple<Int32, Int32>(15, 6)
                                   };

      foreach (Tuple<Int32, Int32> validStationNumber in validStationNumbers)
      {
        Int32 stockId = validStationNumber.Item1;
        Int32 stationNumber = validStationNumber.Item2;

        var stockToAdd = new List<AssignStockViewModel>
                                        {
                                          new AssignStockViewModel { StockId = stockId, StationNumber = stationNumber }
                                        };

        var fakeMediaStockId = 100 + stockId;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeMediaStockId, StationNumber = stationNumber });

        JsonResult result = this.jobsAdminController.AddMediaStockIsAvailable(1, "LaserStock", stockToAdd);

        result.Data.ToString().Should().Be("{ Result = True }");
      }
    }

    [Test]
    public void GivenValidData_WhenICheckIfMediaStockCanBeAdded_AndTheNumberIsInvalidForTrays_AFailureObjectIsReturned()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity>
                         {
                           new StockEntity { StockId = 10, Code = "STATA" },
                           new StockEntity { StockId = 11, Code = "STATB" },
                           new StockEntity { StockId = 12, Code = "STATC" },
                           new StockEntity { StockId = 13, Code = "STATD" },
                           new StockEntity { StockId = 14, Code = "STATE" },
                           new StockEntity { StockId = 15, Code = "STATF" },
                           new StockEntity { StockId = 16, Code = "Code1" }
                         };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      // Item1 = StockId
      // Item2 = Station Number
      var invalidStationNumbers = new List<Tuple<Int32, Int32>>
                                    {
                                      new Tuple<Int32, Int32>(10, 3),
                                      new Tuple<Int32, Int32>(11, 4),
                                      new Tuple<Int32, Int32>(12, 5),
                                      new Tuple<Int32, Int32>(13, 6),
                                      new Tuple<Int32, Int32>(14, 1),
                                      new Tuple<Int32, Int32>(15, 2),
                                      new Tuple<Int32, Int32>(16, 1),
                                    };

      foreach (Tuple<Int32, Int32> invalidStationNumber in invalidStationNumbers)
      {
        Int32 stockId = invalidStationNumber.Item1;
        Int32 stationNumber = invalidStationNumber.Item2;

        var stockToAdd = new List<AssignStockViewModel>
                           {
                             new AssignStockViewModel { StockId = stockId, StationNumber = stationNumber }
                           };

        var fakeMediaStockId = 100 + stockId;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeMediaStockId, StationNumber = stationNumber });

        var result = this.jobsAdminController.AddMediaStockIsAvailable(1, "LaserStock", stockToAdd);

        result.Data.ToString().Should().Be("{ Result = False }");
      }
    }

    [Test]
    public void GivenValidData_WhenICheckIfMediaStockCanBeAdded_AndTheNumberIsInvalidForTrays2_AFailureObjectIsReturned()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity> { new StockEntity { StockId = 2, Code = "STATA" } };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var invalidStationNumbers = new List<Int32> { -1, 0, 7, 100 };

      foreach (Int32 validStationNumber in invalidStationNumbers)
      {
        var stockToAdd = new List<AssignStockViewModel>
                           {
                             new AssignStockViewModel { StockId = 2, StationNumber = validStationNumber }
                           };

        var fakeStockId = 100 + validStationNumber;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeStockId, StationNumber = validStationNumber });

        JsonResult result = this.jobsAdminController.AddMediaStockIsAvailable(1, "LaserStock", stockToAdd);

        result.Data.ToString().Should().Be("{ Result = False }");
      }
    }

    [Test]
    public void GivenValidData_WhenICheckIfMediaStockCanBeAdded_AndTheNumberIsValidForInserts_ASuccessObjectIsReturned()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity> { new StockEntity { StockId = 2, Code = "Code1" } };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var validStationNumbers = new List<Int32> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

      foreach (Int32 validStationNumber in validStationNumbers)
      {
        var stockToAdd = new List<AssignStockViewModel>
                           {
                             new AssignStockViewModel
                               {
                                 StockId = 2,
                                 StationNumber = validStationNumber
                               }
                           };

        var fakeStockId = 100 + validStationNumber;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeStockId, StationNumber = validStationNumber });

        JsonResult result = this.jobsAdminController.AddMediaStockIsAvailable(1, "Insert", stockToAdd);

        result.Data.ToString().Should().Be("{ Result = True }");
      }
    }

    [Test]
    public void GivenValidData_WhenICheckIfMediaStockCanBeAdded_AndTheNumberIsInvalidForInserts_AFailureObjectIsReturned()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity> { new StockEntity { StockId = 2, Code = "Code1" } };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var invalidStationNumbers = new List<Int32> { -1, 0, 10, 100 };

      foreach (Int32 validStationNumber in invalidStationNumbers)
      {
        var stockToAdd = new List<AssignStockViewModel>
                           {
                             new AssignStockViewModel
                               {
                                 StockId = 2,
                                 StationNumber = validStationNumber
                               }
                           };

        var fakeStockId = 100 + validStationNumber;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeStockId, StationNumber = validStationNumber });

        JsonResult result = this.jobsAdminController.AddMediaStockIsAvailable(1, "Insert", stockToAdd);

        result.Data.ToString().Should().Be("{ Result = False }");
      }
    }

    [Test]
    public void GivenValidData_WhenICheckIfMediaStockCanBeAdded_AndTheNumberIsValidForEnvelopes_ASuccessObjectIsReturned()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity> { new StockEntity { StockId = 2, Code = "Code1" } };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var validStationNumbers = new List<Int32> { 0 };

      foreach (Int32 validStationNumber in validStationNumbers)
      {
        var stockToAdd = new List<AssignStockViewModel>
                                        {
                                          new AssignStockViewModel { StockId = 2, StationNumber = validStationNumber }
                                        };

        var fakeStockId = 100 + validStationNumber;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeStockId, StationNumber = validStationNumber });

        JsonResult result = this.jobsAdminController.AddMediaStockIsAvailable(1, "Outer", stockToAdd);

        result.Data.ToString().Should().Be("{ Result = True }");
      }
    }

    [Test]
    public void GivenValidData_WhenICheckIfMediaStockCanBeAdded_AndTheNumberIsInvalidForEnvelopes_AFailureObjectIsReturned()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity> { new StockEntity { StockId = 2, Code = "Code1" } };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var invalidStationNumbers = new List<Int32> { -1, 1, 2, 100 };

      foreach (Int32 validStationNumber in invalidStationNumbers)
      {
        var stockToAdd = new List<AssignStockViewModel>
                                        {
                                          new AssignStockViewModel { StockId = 2, StationNumber = validStationNumber }
                                        };

        var fakeStockId = 100 + validStationNumber;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeStockId, StationNumber = validStationNumber });

        JsonResult result = this.jobsAdminController.AddMediaStockIsAvailable(1, "Outer", stockToAdd);

        result.Data.ToString().Should().Be("{ Result = False }");
      }
    }

    [Test]
    public void GivenValidData_WhenIAddMediaStock_TheDatabaseIsUpdated()
    {
      var existingMediaStockItems = new List<MediaStockEntity>
                                      {
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 1,
                                            StockId = 1,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 1
                                          },
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 2,
                                            StockId = 2,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 2
                                          }
                                      };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItems);

      var stockItems = new List<StockEntity>
                         {
                           new StockEntity { StockId = 10, Code = "STATD" },
                           new StockEntity { StockId = 15, Code = "STATC" }
                         };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var stockToAdd = new List<AssignStockViewModel>
                         {
                           new AssignStockViewModel { StockId = 10, StationNumber = 4 },
                           new AssignStockViewModel { StockId = 15, StationNumber = 3 }
                         };

      var itemsAdded = new List<Tuple<Int32, Int32>>();

      Int32 invocationNum = 0;
      this.mediaStockServiceMock.Setup(s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
        .Returns<Int32, Int32, Int32>(
          (stockId, mediaDefinitionId, stationNumber) =>
            {
              itemsAdded.Add(new Tuple<Int32, Int32>(stockId, stationNumber));

              invocationNum++;
              switch (invocationNum)
              {
                case 1:
                  return new MediaStockEntity { MediaStockId = 3, StockId = 10, StationNumber = 4 };
                case 2:
                  return new MediaStockEntity { MediaStockId = 4, StockId = 15, StationNumber = 3 };
                default:
                  throw new Exception("Third invocation not supported in test");
              }
            });

      this.jobsAdminController.AddMediaStock(1, "LaserStock", stockToAdd, String.Empty);

      this.mediaStockServiceMock.Verify(s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Exactly(2));

      itemsAdded.Count.Should().Be(2);
      itemsAdded[0].Item1.Should().Be(10); // Stock Id
      itemsAdded[0].Item2.Should().Be(4); // Station Number
      itemsAdded[1].Item1.Should().Be(15); // Stock Id
      itemsAdded[1].Item2.Should().Be(3); // Station Number
    }

    [Test]
    public void GivenValidData_WhenIAddMediaStock_TheViewModelIsConstructed()
    {
      var existingMediaStockItems = new List<MediaStockEntity>
                                      {
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 1,
                                            StockId = 1,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 1
                                          },
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 2,
                                            StockId = 2,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 2
                                          }
                                      };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItems);

      var stockItems = new List<StockEntity>
                         {
                           new StockEntity { StockId = 10, Code = "STATD" },
                           new StockEntity { StockId = 15, Code = "STATC" }
                         };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var stockToAdd = new List<AssignStockViewModel>
                         {
                           new AssignStockViewModel { StockId = 10, StationNumber = 4 },
                           new AssignStockViewModel { StockId = 15, StationNumber = 3 }
                         };

      var itemsAdded = new List<Tuple<Int32, Int32>>();

      Int32 invocationNum = 0;
      this.mediaStockServiceMock.Setup(s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
        .Returns<Int32, Int32, Int32>(
          (stockId, mediaDefinitionId, stationNumber) =>
          {
            itemsAdded.Add(new Tuple<Int32, Int32>(stockId, stationNumber));

            invocationNum++;
            switch (invocationNum)
            {
              case 1:
                return new MediaStockEntity { MediaStockId = 3, StockId = 11, StationNumber = 4 };
              case 2:
                return new MediaStockEntity { MediaStockId = 4, StockId = 16, StationNumber = 3 };
              default:
                throw new Exception("Third invocation not supported in test");
            }
          });

      PartialViewResult result = this.jobsAdminController.AddMediaStock(1, "LaserStock", stockToAdd, String.Empty);

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<StockAssignmentViewModel>();
      var model = (StockAssignmentViewModel)modelObject;

      model.MediaDefinitionId.Should().Be(1);
      model.StockType.Should().Be("LaserStock");
      model.DisplayStockType.Should().Be("Trays");
      model.Filter.Should().Be(String.Empty);

      model.ExistingStock.Should().HaveCount(4);
      model.ExistingStock[0].MediaStockId.Should().Be(1);
      model.ExistingStock[0].StationNumber.Should().Be(1);
      model.ExistingStock[1].MediaStockId.Should().Be(2);
      model.ExistingStock[1].StationNumber.Should().Be(2);
      model.ExistingStock[2].MediaStockId.Should().Be(4);
      model.ExistingStock[2].StationNumber.Should().Be(3);
      model.ExistingStock[3].MediaStockId.Should().Be(3);
      model.ExistingStock[3].StationNumber.Should().Be(4);
    }

    [Test]
    public void GivenValidData_WhenIAddMediaStock_AndADuplicateIsFound_AnExceptionIsRaised()
    {
      var existingMediaStockItems = new List<MediaStockEntity>
                                      {
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 1,
                                            StockId = 1,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 1
                                          },
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 2,
                                            StockId = 2,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 2
                                          }
                                      };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItems);

      var stockItems = new List<StockEntity>
                         {
                           new StockEntity { StockId = 10, Code = "STATB" }
                         };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var stockToAdd = new List<AssignStockViewModel>
                         {
                           new AssignStockViewModel { StockId = 10, StationNumber = 2 }
                         };

      this.mediaStockServiceMock
        .Setup(s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
        .Returns(new MediaStockEntity { MediaStockId = 3, StockId = 11, StationNumber = 4 });

      try
      {
        this.jobsAdminController.AddMediaStock(1, "LaserStock", stockToAdd, String.Empty);
      }
      catch (Exception ex)
      {
        ex.Message.Should().Be("Station number duplicated");
        return;
      }

      Assert.Fail("Should raise a station number duplicated exception");
    }

    [Test]
    public void GivenValidData_WhenIAddMediaStock_WithDuplicatesInTheSubmittedData_AnExceptionIsRaised()
    {
      var existingMediaStockItem = new List<MediaStockEntity>
                                      {
                                        new MediaStockEntity
                                          {
                                            MediaStockId = 1,
                                            StockId = 1,
                                            MediaDefId = 1,
                                            StockTypeId = 1,
                                            StockType = "LaserStock",
                                            StationNumber = 1
                                          }
                                      };

      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(existingMediaStockItem);

      var stockItems = new List<StockEntity>
                         {
                           new StockEntity { StockId = 10, Code = "STATB" },
                           new StockEntity { StockId = 15, Code = "STATB" }
                         };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var stockToAdd = new List<AssignStockViewModel>
                         {
                           new AssignStockViewModel { StockId = 10, StationNumber = 2 },
                           new AssignStockViewModel { StockId = 15, StationNumber = 2 }
                         };

      try
      {
        this.jobsAdminController.AddMediaStock(1, "LaserStock", stockToAdd, String.Empty);
      }
      catch (Exception ex)
      {
        ex.Message.Should().Be("Station number duplicated");
        return;
      }

      Assert.Fail("Should raise a station number duplicated exception");
    }

    [Test]
    public void GivenValidData_WhenIAddMediaStock_AndTheNumberIsValidForTrays_NoExceptionIsRaised()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity>
                         {
                           new StockEntity { StockId = 10, Code = "STATA" },
                           new StockEntity { StockId = 11, Code = "STATB" },
                           new StockEntity { StockId = 12, Code = "STATC" },
                           new StockEntity { StockId = 13, Code = "STATD" },
                           new StockEntity { StockId = 14, Code = "STATE" },
                           new StockEntity { StockId = 15, Code = "STATF" }
                         };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      // Item1 = StockId
      // Item2 = Station Number
      var validStationNumbers = new List<Tuple<Int32, Int32>>
                                   {
                                     new Tuple<Int32, Int32>(10, 1),
                                     new Tuple<Int32, Int32>(11, 2),
                                     new Tuple<Int32, Int32>(12, 3),
                                     new Tuple<Int32, Int32>(13, 4),
                                     new Tuple<Int32, Int32>(14, 5),
                                     new Tuple<Int32, Int32>(15, 6)
                                   };

      foreach (Tuple<Int32, Int32> validStationNumber in validStationNumbers)
      {
        Int32 stockId = validStationNumber.Item1;
        Int32 stationNumber = validStationNumber.Item2;

        var stockToAdd = new List<AssignStockViewModel>
                                        {
                                          new AssignStockViewModel { StockId = stockId, StationNumber = stationNumber }
                                        };

        var fakeMediaStockId = 100 + stockId;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeMediaStockId, StationNumber = stationNumber });

        Action act = () => this.jobsAdminController.AddMediaStock(1, "LaserStock", stockToAdd, String.Empty);

        act.ShouldNotThrow();
      }
    }

    [Test]
    public void GivenValidData_WhenIAddMediaStock_AndTheNumberIsInvalidForTrays_AnExceptionIsRaised()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity>
                         {
                           new StockEntity { StockId = 10, Code = "STATA" },
                           new StockEntity { StockId = 11, Code = "STATB" },
                           new StockEntity { StockId = 12, Code = "STATC" },
                           new StockEntity { StockId = 13, Code = "STATD" },
                           new StockEntity { StockId = 14, Code = "STATE" },
                           new StockEntity { StockId = 15, Code = "STATF" },
                           new StockEntity { StockId = 16, Code = "Code1" }
                         };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      // Item1 = StockId
      // Item2 = Station Number
      var invalidStationNumbers = new List<Tuple<Int32, Int32>>
                                   {
                                     new Tuple<Int32, Int32>(10, 3),
                                     new Tuple<Int32, Int32>(11, 4),
                                     new Tuple<Int32, Int32>(12, 5),
                                     new Tuple<Int32, Int32>(13, 6),
                                     new Tuple<Int32, Int32>(14, 1),
                                     new Tuple<Int32, Int32>(15, 2),
                                     new Tuple<Int32, Int32>(16, 1),
                                   };

      foreach (Tuple<Int32, Int32> invalidStationNumber in invalidStationNumbers)
      {
        Int32 stockId = invalidStationNumber.Item1;
        Int32 stationNumber = invalidStationNumber.Item2;

        var stockToAdd = new List<AssignStockViewModel>
                                        {
                                          new AssignStockViewModel { StockId = stockId, StationNumber = stationNumber }
                                        };

        var fakeMediaStockId = 100 + stockId;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeMediaStockId, StationNumber = stationNumber });

        try
        {
          this.jobsAdminController.AddMediaStock(1, "LaserStock", stockToAdd, String.Empty);
        }
        catch (Exception ex)
        {
          ex.Message.Should().Be("Station number invalid");
          continue;
        }

        Assert.Fail("An exception should have been raised");
      }
    }

    [Test]
    public void GivenValidData_WhenIAddMediaStock_AndTheNumberIsInvalidForTrays2_NoExceptionIsRaised()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity> { new StockEntity { StockId = 2, Code = "STATA" } };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var invalidStationNumbers = new List<Int32> { -1, 0, 7, 100 };

      foreach (Int32 validStationNumber in invalidStationNumbers)
      {
        var stockToAdd = new List<AssignStockViewModel>
                           {
                             new AssignStockViewModel { StockId = 2, StationNumber = validStationNumber }
                           };

        var fakeStockId = 100 + validStationNumber;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeStockId, StationNumber = validStationNumber });

        try
        {
          this.jobsAdminController.AddMediaStock(1, "LaserStock", stockToAdd, String.Empty);
        }
        catch (Exception ex)
        {
          ex.Message.Should().Be("Station number invalid");
        }
      }
    }

    [Test]
    public void GivenValidData_WhenIAddMediaStock_AndTheNumberIsValidForInserts_NoExceptionIsRaised()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity> { new StockEntity { StockId = 2, Code = "Code1" } };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var validStationNumbers = new List<Int32> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

      foreach (Int32 validStationNumber in validStationNumbers)
      {
        var stockToAdd = new List<AssignStockViewModel>
                                        {
                                          new AssignStockViewModel { StockId = 2, StationNumber = validStationNumber }
                                        };

        var fakeStockId = 100 + validStationNumber;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeStockId, StationNumber = validStationNumber });

        Action act = () => this.jobsAdminController.AddMediaStock(1, "Insert", stockToAdd, String.Empty);

        act.ShouldNotThrow();
      }
    }

    [Test]
    public void GivenValidData_WhenIAddMediaStock_AndTheNumberIsInvalidForInserts_NoExceptionIsRaised()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity> { new StockEntity { StockId = 2, Code = "STATA" } };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var invalidStationNumbers = new List<Int32> { -1, 0, 10, 100 };

      foreach (Int32 validStationNumber in invalidStationNumbers)
      {
        var stockToAdd = new List<AssignStockViewModel>
                                        {
                                          new AssignStockViewModel { StockId = 2, StationNumber = validStationNumber }
                                        };

        var fakeStockId = 100 + validStationNumber;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeStockId, StationNumber = validStationNumber });

        try
        {
          this.jobsAdminController.AddMediaStock(1, "Insert", stockToAdd, String.Empty);
        }
        catch (Exception ex)
        {
          ex.Message.Should().Be("Station number invalid");
        }
      }
    }

    [Test]
    public void GivenValidData_WhenIAddMediaStock_AndTheNumberIsValidForEnvelopes_NoExceptionIsRaised()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity> { new StockEntity { StockId = 2, Code = "Code1" } };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var validStationNumbers = new List<Int32> { 0 };

      foreach (Int32 validStationNumber in validStationNumbers)
      {
        var stockToAdd = new List<AssignStockViewModel>
                                        {
                                          new AssignStockViewModel { StockId = 2, StationNumber = validStationNumber }
                                        };

        var fakeStockId = 100 + validStationNumber;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeStockId, StationNumber = validStationNumber });

        Action act = () => this.jobsAdminController.AddMediaStock(1, "Outer", stockToAdd, String.Empty);

        act.ShouldNotThrow();
      }
    }

    [Test]
    public void GivenValidData_WhenIAddMediaStock_AndTheNumberIsInvalidForEnvelopes_NoExceptionIsRaised()
    {
      this.mediaStockServiceMock.Setup(s => s.GetByMediaDefinition(It.IsAny<Int32>())).Returns(new List<MediaStockEntity>());

      var stockItems = new List<StockEntity> { new StockEntity { StockId = 2, Code = "Code1" } };

      this.stockServiceMock.Setup(s => s.GetStockByType(It.IsAny<String>(), It.IsAny<String>())).Returns(stockItems);

      var invalidStationNumbers = new List<Int32> { -1, 1, 2, 100 };

      foreach (Int32 validStationNumber in invalidStationNumbers)
      {
        var stockToAdd = new List<AssignStockViewModel>
                                        {
                                          new AssignStockViewModel { StockId = 2, StationNumber = validStationNumber }
                                        };

        var fakeStockId = 100 + validStationNumber;

        this.mediaStockServiceMock.SetupSequence(
          s => s.AddMediaStock(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()))
          .Returns(new MediaStockEntity { MediaStockId = fakeStockId, StationNumber = validStationNumber });

        try
        {
          this.jobsAdminController.AddMediaStock(1, "Outer", stockToAdd, String.Empty);
        }
        catch (Exception ex)
        {
          ex.Message.Should().Be("Station number invalid");
        }
      }
    }

    [Test]
    public void GivenAStockTypeName_WhenTheCreateStockPageIsRequested_TheViewModelIsConstructedWithTheCorrectDefaults()
    {
      ViewResult result = this.jobsAdminController.CreateStock("StockType");

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<CreateStockViewModel>();
      var model = (CreateStockViewModel)modelObject;

      model.StockType.Should().Be("StockType");
      model.CodesAreRestricted.Should().BeFalse();
      model.AvailableCodes.Should().HaveCount(0);
      model.Code.Should().Be(null);
      model.Description.Should().Be(null);

      model.Weight.Should().Be(0);
      model.SizeX.Should().Be(0);
      model.SizeY.Should().Be(0);
      model.Facing.Should().Be('0');
      model.Colour.Should().Be("White");
    }

    [Test]
    public void GivenATrayStockType_WhenTheCreateStockPageIsRequested_TheViewModelIsConstructedWithTheCorrectDefaults()
    {
      ViewResult result = this.jobsAdminController.CreateStock("LaserStock");

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<CreateStockViewModel>();
      var model = (CreateStockViewModel)modelObject;

      model.StockType.Should().Be("LaserStock");
      model.CodesAreRestricted.Should().BeTrue();
      model.AvailableCodes.Should().HaveCount(6);
      model.AvailableCodes.Should().BeInAscendingOrder();
      model.AvailableCodes.Should().BeEquivalentTo(new[] { "STATA", "STATB", "STATC", "STATD", "STATE", "STATF" });
      model.Code.Should().Be(null);
      model.Description.Should().Be(null);

      model.Weight.Should().Be(0);
      model.SizeX.Should().Be(0);
      model.SizeY.Should().Be(0);
      model.Facing.Should().Be('0');
      model.Colour.Should().Be("White");
    }
    
    [Test]
    public void GivenAStockTypeName_WhenTheCreateStockPageIsRequested_AndTheStockTypeIsInvalid_AnExceptionIsRaised()
    {
      this.stockServiceMock.Setup(s => s.GetStockTypeId(It.IsAny<String>())).Throws(new Exception("StockType not supported"));

      Action action = () => this.jobsAdminController.CreateStock("StockType");

      action.ShouldThrow<Exception>();
    }

    [Test]
    public void GivenValidData_WhenICreateNewStock_TheDatabaseIsUpdated()
    {
      var model = new CreateStockViewModel
                    {
                      StockType = "stockType",
                      Code = "code",
                      Description = "description",
                      Weight = 3,
                      SizeX = 4,
                      SizeY = 5,
                      Facing = 'F',
                      Colour = "colour"
                    };

      this.stockServiceMock.Setup(s => s.GetStockTypeId("stockType")).Returns(1);

      this.stockServiceMock.Setup(
        s =>
        s.CreateStock(
          It.IsAny<Int32>(),
          It.IsAny<String>(),
          It.IsAny<String>(),
          It.IsAny<Int32>(),
          It.IsAny<Int32>(),
          It.IsAny<Int32>(),
          It.IsAny<Char>(),
          It.IsAny<String>())).Returns(new StockEntity { StockId = 1 });

      this.jobsAdminController.CreateStock(model);

      this.stockServiceMock.Verify(s => s.CreateStock(1, "code", "description", 3, 4, 5, 'F', "colour"), Times.Once());
    }

    [Test]
    public void GivenValidData_WhenICreateNewStock_ASuccessObjectIsReturned()
    {
      var model = new CreateStockViewModel
      {
        StockType = "stockType",
        Code = "code",
        Description = "description",
        Weight = 0,
        SizeX = 0,
        SizeY = 0,
        Facing = 'F',
        Colour = "colour"
      };

      this.stockServiceMock.Setup(
        s =>
        s.CreateStock(
          It.IsAny<Int32>(),
          It.IsAny<String>(),
          It.IsAny<String>(),
          It.IsAny<Int32>(),
          It.IsAny<Int32>(),
          It.IsAny<Int32>(),
          It.IsAny<Char>(),
          It.IsAny<String>())).Returns(new StockEntity { StockId = 1 });

      JsonResult result = this.jobsAdminController.CreateStock(model);

      String json = new JavaScriptSerializer().Serialize(result.Data);
      json.Should().Be("{\"Success\":true,\"StockId\":1}");
    }

    [Test]
    public void GivenValidData_WhenICreateNewStock_AndTheCreationFails_AnExceptionIsRaised()
    {
      var model = new CreateStockViewModel
      {
        StockType = "stockType",
        Code = "code",
        Description = "description",
        Weight = 0,
        SizeX = 0,
        SizeY = 0,
        Facing = 'F',
        Colour = "colour"
      };

      this.stockServiceMock.Setup(
        s =>
        s.CreateStock(
          It.IsAny<Int32>(),
          It.IsAny<String>(),
          It.IsAny<String>(),
          It.IsAny<Int32>(),
          It.IsAny<Int32>(),
          It.IsAny<Int32>(),
          It.IsAny<Char>(),
          It.IsAny<String>())).Throws<Exception>();

      Action act = () => this.jobsAdminController.CreateStock(model);

      act.ShouldThrow<Exception>();
    }

    [Test]
    public void GivenValidData_WhenICreateNewStock_AndTheCodeIsMissing_AFailureObjectIsReturned()
    {
      var model = new CreateStockViewModel
      {
        StockType = "stockType",
        Code = String.Empty,
        Description = "description",
        Weight = 0,
        SizeX = 0,
        SizeY = 0,
        Facing = 'F',
        Colour = "colour"
      };

      JsonResult result = this.jobsAdminController.CreateStock(model);

      String json = new JavaScriptSerializer().Serialize(result.Data);
      json.Should().Be("{\"Success\":false,\"Failures\":[\"Code required\"]}");
    }

    [Test]
    public void GivenValidData_WhenICreateNewStock_AndTheCodeIsInvalid_AFailureObjectIsReturned()
    {
      var model = new CreateStockViewModel
      {
        StockType = "LaserStock",
        Code = "RandomCode",
        Description = "description",
        Weight = 0,
        SizeX = 0,
        SizeY = 0,
        Facing = 'F',
        Colour = "colour"
      };

      JsonResult result = this.jobsAdminController.CreateStock(model);

      String json = new JavaScriptSerializer().Serialize(result.Data);
      json.Should().Be("{\"Success\":false,\"Failures\":[\"Code invalid\"]}");
    }

    [Test]
    public void GivenValidData_WhenICreateNewStock_AndTheDescriptionIsMissing_AFailureObjectIsReturned()
    {
      var model = new CreateStockViewModel
      {
        StockType = "stockType",
        Code = "code",
        Description = String.Empty,
        Weight = 0,
        SizeX = 0,
        SizeY = 0,
        Facing = 'F',
        Colour = "colour"
      };

      JsonResult result = this.jobsAdminController.CreateStock(model);

      String json = new JavaScriptSerializer().Serialize(result.Data);
      json.Should().Be("{\"Success\":false,\"Failures\":[\"Description required\"]}");
    }

    [Test]
    public void GivenValidData_WhenICreateNewStock_AndTheColourIsMissing_AFailureObjectIsReturned()
    {
      var model = new CreateStockViewModel
      {
        StockType = "stockType",
        Code = "code",
        Description = "description",
        Weight = 0,
        SizeX = 0,
        SizeY = 0,
        Facing = 'F',
        Colour = String.Empty
      };

      JsonResult result = this.jobsAdminController.CreateStock(model);
      String json = new JavaScriptSerializer().Serialize(result.Data);
      json.Should().Be("{\"Success\":false,\"Failures\":[\"Colour required\"]}");
    }

    [Test]
    public void GivenValidData_WhenICreateNewStock_AndMultipleValidationFailuresExist_AFailureObjectIsReturnedContainingAllFailures()
    {
      var model = new CreateStockViewModel
      {
        StockType = "stockType",
        Code = String.Empty,
        Description = String.Empty,
        Weight = 0,
        SizeX = 0,
        SizeY = 0,
        Facing = 'F',
        Colour = "colour"
      };

      JsonResult result = this.jobsAdminController.CreateStock(model);
      String json = new JavaScriptSerializer().Serialize(result.Data);
      json.Should().Be("{\"Success\":false,\"Failures\":[\"Code required\",\"Description required\"]}");
    }

    [Test]
    public void GivenValidData_WhenICreateNewStock_AndADuplicateIsFound_AFailureObjectIsReturned()
    {
      var model = new CreateStockViewModel
      {
        StockType = "stockType",
        Code = "code",
        Description = "description",
        Weight = 0,
        SizeX = 0,
        SizeY = 0,
        Facing = 'F',
        Colour = "colour"
      };

      this.stockServiceMock.Setup(
        s =>
        s.CreateStock(
          It.IsAny<Int32>(),
          It.IsAny<String>(),
          It.IsAny<String>(),
          It.IsAny<Int32>(),
          It.IsAny<Int32>(),
          It.IsAny<Int32>(),
          It.IsAny<Char>(),
          It.IsAny<String>())).Throws(new DocProcessingException("Duplicate stock item found"));

      JsonResult result = this.jobsAdminController.CreateStock(model);
      String json = new JavaScriptSerializer().Serialize(result.Data);
      json.Should().Be("{\"Success\":false,\"Failures\":[\"Duplicate stock item found\"]}");
    }

    [Test]
    public void GivenValidData_WhenTheMailSortSettingsPageIsRequested_TheViewModelIsConstructed()
    {
      this.mailSortSettingServiceMock.Setup(m => m.GetMailsortSettings())
        .Returns(
          new List<MailsortSetting>
            {
              new MailsortSetting
                {
                  MailsortSettingID = 1,
                  TNTDepot = "tntDepot",
                  TNTMailingHouse = "tntMailingHouse",
                  TNTClientCode = "tntClientCode",
                  TNTJobReference = "tntJobReference",
                  nexdoxMailsortService = "nexdoxMailSortService",
                  largeletter = true,
                  FixedWeight_NoOuter = 9
                }
            });

      ViewResult result = this.jobsAdminController.MailSortSettings();

      Object modelObject = result.ViewData.Model;
      modelObject.Should().BeOfType<MailSortSettingsViewModel>();
      var model = (MailSortSettingsViewModel)modelObject;

      model.MailSortSettings.Should().HaveCount(1);
      model.MailSortSettings[0].MailsortSettingID.Should().Be(1);
      model.MailSortSettings[0].TNTDepot.Should().Be("tntDepot");
      model.MailSortSettings[0].TNTMailingHouse.Should().Be("tntMailingHouse");
      model.MailSortSettings[0].TNTClientCode.Should().Be("tntClientCode");
      model.MailSortSettings[0].TNTJobReference.Should().Be("tntJobReference");
      model.MailSortSettings[0].NexdoxMailsortService.Should().Be("nexdoxMailSortService");
      model.MailSortSettings[0].Largeletter.Should().BeTrue();
      model.MailSortSettings[0].FixedWeight_NoOuter.Should().Be(9);
    }

    [Test]
    public void GivenValidData_WhenTheAddMailSortSettingPageIsRequested_ThePageIsReturned()
    {
      ViewResult result = this.jobsAdminController.AddMailSortSetting();
      result.Should().NotBeNull();
    }

    [Test]
    public void GivenValidData_WhenTheAddMailSortSettingPageIsPosted_TheDatabaseIsUpdated()
    {
      var mailSortSetting = new MailSortSettingViewModel
                              {
                                TNTDepot = "tntDepot",
                                TNTMailingHouse = "tntMailingHouse",
                                TNTClientCode = "tntClientCode",
                                TNTJobReference = "tntJobReference",
                                NexdoxMailsortService = "nexdoxMailSortService",
                                Largeletter = true,
                                FixedWeight_NoOuter = 6
                              };

      ActionResult result = this.jobsAdminController.AddMailSortSetting(mailSortSetting);

      this.mailSortSettingServiceMock.Verify(
        m =>
        m.AddMailSortSetting(
          "tntDepot",
          "tntMailingHouse",
          "tntClientCode",
          "tntJobReference",
          "nexdoxMailSortService",
          true,
          6),
        Times.Once);

      result.Should().BeOfType<RedirectToRouteResult>();
      var redirectResult = (RedirectToRouteResult)result;
      redirectResult.RouteValues["action"].Should().Be("MailSortSettings");
    }

    [Test]
    public void GivenInvalidData_WhenTheAddMailSortSettingPageIsPosted_AnErrorMessageIsReturned()
    {
      var mailSortSetting = new MailSortSettingViewModel();

      this.jobsAdminController.ViewData.ModelState.AddModelError("Err1", @"A validation Error");
      this.jobsAdminController.ViewData.ModelState.AddModelError("Err2", @"Another validation Error");

      ActionResult result = this.jobsAdminController.AddMailSortSetting(mailSortSetting);

      this.mailSortSettingServiceMock.Verify(
        m =>
        m.AddMailSortSetting(
          "tntDepot",
          "tntMailingHouse",
          "tntClientCode",
          "tntJobReference",
          "nexdoxMailSortService",
          true,
          6),
        Times.Never);

      result.Should().BeOfType<ViewResult>();
    }
  }
}